<?php
/**
 * 
 *
 * @package api
 * @subpackage collections
 * @author $Author$
 * @version $Id$
 */
/** 
 *
 */
require_once( "util/AbstractList.php" );

/**
 * Abstract class AbstractSequentialList
 *
 * This class provides a skeletal implementation of the List  interface to minimize the effort required to implement 
 * this interface backed by a "sequential access" data store (such as a linked list). For random access data (such as an 
 * array), AbstractList should be used in preference to this class.
 * 
 * This class is the opposite of the AbstractList class in the sense that it implements the "random access" methods 
 * (get(int index), set(int index, Object element), set(int index, Object element), add(int index, Object element) and 
 * remove(int index)) on top of the list's list iterator, instead of the other way around.
 * 
 * To implement a list the programmer needs only to extend this class and provide implementations for the listCollectionIterator 
 * and size methods. For an unmodifiable list, the programmer need only implement the list iterator's hasNext, next, 
 * hasPrevious, previous and index methods.
 * 
 * For a modifiable list the programmer should additionally implement the list iterator's set method. For a variable-size 
 * list the programmer should additionally implement the list iterator's remove and add methods.
 * 
 * The programmer should generally provide a void (no argument) and collection constructor, as per the recommendation in 
 * the Collection interface specification.
 * 
 * This class is a member of the PHP Collections Framework. 
 *
 * @package api
 * @subpackage collections
 * @author $Author$
 * @version $Id$
 */
abstract class AbstractSequentialList extends AbstractList {
	
	/** 
	 * Returns the element at the specified position in this list.
	 *
	 * This implementation first gets a list iterator pointing to the indexed element (with listCollectionIterator(index)). Then, 
	 * it gets the element using ListCollectionIterator.next and returns it.
	 * 
	 * @param int $index index of element to return.
	 * @returns Object the element at the specified position in this list.
	 * @throws {@link IndexOutOfBoundsException} if the specified index is out of range (index < 0 || index >= size()).
	 */
	public function get( $index ) {
		$e = $this->listCollectionIteratorAt( $index );
		try {
			return $e->getNext();
		} catch (NoSuchElementException $exc ) {
			throw new IndexOutOfBoundsException("Index: " . $index );
		}
	}
	
	/** 
	 * Replaces the element at the specified position in this list with the specified element.
	 *
	 * This implementation first gets a list iterator pointing to the indexed element (with listCollectionIterator(index)). Then, 
	 * it gets the current element using ListCollectionIterator.next and replaces it with ListCollectionIterator.set.
	 * 
	 * Note that this implementation will throw an UnsupportedOperationException if list iterator does not implement the 
	 * set operation. 
	 * 
	 * @param int $index index of element to replace.
	 * @param Object $element element to be stored at the specified position.
	 * @returns Object the element previously at the specified position.
	 * @throws {@link UnsupportedOperationException} - set is not supported by this list. 
	 * @throws {@link NullPointerException} - this list does not permit null elements and one of the elements of c is null. 
	 * @throws {@link ClassCastException} - class of the specified element prevents it from being added to this list. 
	 * @throws {@link IllegalArgumentException} - some aspect of the specified element prevents it from being added to this list. 
	 * @throws {@link IndexOutOfBoundsException} - index out of range (index < 0 || index >= size()). 
	 * @throws {@link IllegalArgumentException} - fromIndex > toIndex.
	 */
	public function set( $index, Object $element) {
		$e = $this->listIteratorAt( $index );
		try {
			$oldVal = $e->getNext();
			$e->set( $element );
			return $oldVal;
		} catch (NoSuchElementException $exc ) {
			throw new IndexOutOfBoundsException("Index: " . $index);
		}
	}
	
	/** 
	 * Inserts the specified element at the specified position in this list.
	 *
	 * Inserts the specified element at the specified position in this list. Shifts the element currently at that 
	 * position (if any) and any subsequent elements to the right (adds one to their indices).
	 * 
	 * This implementation first gets a list iterator pointing to the indexed element (with listCollectionIterator(index)). 
	 * Then, it inserts the specified element with ListCollectionIterator.add.
	 * 
	 * Note that this implementation will throw an UnsupportedOperationException if list iterator does not implement 
	 * the add operation. 
	 * 
	 * @param int $index index at which the specified element is to be inserted.
	 * @param Object $element element to be inserted.
	 * @throws {@link UnsupportedOperationException} - if the add operation is not supported by this list. 
	 * @throws {@link NullPointerException} - this list does not permit null elements and one of the elements of c is null. 
	 * @throws {@link ClassCastException} - if the class of the specified element prevents it from being added to this list. 
	 * @throws {@link IllegalArgumentException} - if some aspect of the specified element prevents it from being added to this list. 
	 * @throws {@link IndexOutOfBoundsException} - if the specified index is out of range (index < 0 || index > size()).
	 */
	public function addAt( $index, Object $element ) {
		$e = $this->listIteratorAt($index);
		$e->add( $element );
	}
	
	/** 
	 * Removes the element at the specified position in this list.
	 *
	 * Removes the element at the specified position in this list. Shifts any subsequent elements to the left (subtracts 
	 * one from their indices).
	 * 
	 * This implementation first gets a list iterator pointing to the indexed element (with listCollectionIterator(index)). Then, 
	 * it removes the element with ListCollectionIterator.remove.
	 * 
	 * Note that this implementation will throw an UnsupportedOperationException if list iterator does not implement the 
	 * remove operation. 
	 * 
	 * @param int $index index of the element to be removed from the List.
	 * @returns Object $element the element that was removed from the list.
	 * @throws {@link UnsupportedOperationException} - if the remove operation is not supported by this list. 
	 * @throws {@link IndexOutOfBoundsException} - if the specified index is out of range (index < 0 || index >= size()).
	 */
	public function removeAt( $index ) {
		$e = $this->listIteratorAt( $index );
		$outCast = null;
		try {
			$outCast = $e->getNext();
		} catch (NoSuchElementException $exc ) {
			throw new IndexOutOfBoundsException("Index: " . $index );
		}
		$e->remove();
		return $outCast;
	}
	
	/** 
	 * Inserts all of the elements in the specified collection into this list at the specified position. 
	 *
	 * Inserts all of the elements in the specified collection into this list at the specified position. Shifts the 
	 * element currently at that position (if any) and any subsequent elements to the right (increases their indices). 
	 * The new elements will appear in the list in the order that they are returned by the specified collection's iterator. 
	 * The behavior of this operation is unspecified if the specified collection is modified while the operation is in 
	 * progress. (Note that this will occur if the specified collection is this list, and it's nonempty.) Optional operation.
	 * 
	 * This implementation gets an iterator over the specified collection and a list iterator over this list pointing to the 
	 * indexed element (with listCollectionIterator(index)). Then, it iterates over the specified collection, inserting the elements 
	 * obtained from the iterator into this list, one at a time, using ListCollectionIterator.add followed by ListCollectionIterator.next (to 
	 * skip over the added element).
	 * 
	 * Note that this implementation will throw an UnsupportedOperationException if the list iterator returned by the 
	 * listCollectionIterator method does not implement the add operation. 
	 * 
	 * @param int $index index at which to insert first element from the specified collection.
	 * @param Collection $c elements to be inserted into this list.
	 * @returns boolean true if this list changed as a result of the call.
	 * @throws {@link UnsupportedOperationException} - if the addAllAt operation is not supported by this list. 
	 * @throws {@link NullPointerException} - this list does not permit null elements and one of the elements of c is null. 
	 * @throws {@link ClassCastException} - if the class of the specified element prevents it from being added to this list. 
	 * @throws {@link IllegalArgumentException} - if some aspect of the specified element prevents it from being added to this list. 
	 * @throws {@link IndexOutOfBoundsException} - if the specified index is out of range (index < 0 || index > size()).
	 */
	public function addAllAt( $index, Collection $c ) {
		$modified = false;
		$e1 = $this->listIteratorAt( $index );
		$e2 = $c->iterator();
		while ($e2->hasNext()) {
			$e1->add( $e2->getNext() );
			$modified = true;
		}
		return $modified;
	}
	
	/**
	 * Returns an iterator over the elements in this list (in proper sequence).
	 * 
	 * This implementation merely returns a list iterator over the list. 
	 * 
	 * @returns CollectionIterator an iterator over the elements in this list (in proper sequence).
	 */
	public function iterator() {
		return $this->listIteratorAt(0);
	}
}


?>